import 'dart:convert';
import 'dart:math';

import 'package:bigegg/common/log/xmm_logcat.dart';
import 'package:bigegg/data/repository/xmm_local_repository.dart';
import 'package:bigegg/entity/articel/xmm_article_info.dart';
import 'package:bigegg/entity/user/xmm_app_config.dart';
import 'package:bigegg/entity/user/xmm_login.dart';
import 'package:bigegg/entity/user/xmm_wall_user.dart';
import 'package:bigegg/entity/xmm_video_info.dart';
import 'package:bigegg/global/im/xmm_im_manager.dart';
import 'package:bigegg/global/xmm_app_const.dart';
import 'package:bigegg/page/im/chat/xmm_chat_controller.dart';
import 'package:bigegg/page/main/page/home/xmm_home_controller.dart';
import 'package:bigegg/page/main/page/im/page/xmm_conversation_controller.dart';
import 'package:bigegg/page/main/page/im/page/xmm_follow_controller.dart';
import 'package:bigegg/page/main/page/mine/page/xmm_block_list_controller.dart';
import 'package:bigegg/page/main/page/video/xmm_video_controller.dart';
import 'package:bigegg/utils/xmm_event_bus.dart';
import 'package:get/get.dart';

import '../../common/log/xmm_log.dart';
import '../../common/sp/xmm_shared_preferences_util.dart';
import '../../data/repository/xmm_remote_repository.dart';
import '../../entity/user/xmm_block_user.dart';
import '../../entity/user/xmm_strategy.dart';
import '../../entity/user/xmm_user.dart';
import '../../page/main/page/im/xmm_im_controller.dart';
import '../../utils/xmm_platform_utils.dart';

class XmmAccountManager {
  static XmmAccountManager? _instance;

  static XmmAccountManager get instance =>
      _instance ??= XmmAccountManager._internal();

  XmmAccountManager._internal();

  ///登录token
  String? _token;

  String? get token => _token;

  ///用户数据
  Rx<XmmUser> _user = XmmUser().obs;

  XmmUser get user => _user.value;

  ///登录用户
  XmmLogin? _login;

  XmmLogin? get login => _login;

  ///策略数据
  XmmStrategy? _strategy;

  XmmStrategy? get strategy => _strategy;

  ///配置数据
  XmmAppConfig? _appConfig;

  XmmAppConfig? get appConfig => _appConfig;

  ///我的作品列表
  final RxList<XmmArticleInfo> _myArticleInfoList = <XmmArticleInfo>[].obs;

  Iterable<XmmArticleInfo> get myArticleInfoList => _myArticleInfoList.value;

  ///首页用户列表
  List<XmmWallUser> _wallUserList = <XmmWallUser>[];

  Iterable<XmmWallUser> get wallUserList => _wallUserList;

  ///首页作品列表
  List<XmmArticleInfo> _articleInfoList = <XmmArticleInfo>[];

  Iterable<XmmArticleInfo> get articleInfoList => _articleInfoList;

  ///首页视频列表
  List<XmmVideoInfo> _videoInfoList = <XmmVideoInfo>[];

  Iterable<XmmVideoInfo> get videoInfoList => _videoInfoList;

  ///是否支持自动登录
  bool get isSupportAutoLogin {
    return XmmSPUtil.get(XmmAppConst.spLoginTokenKey) != null &&
        XmmSPUtil.get(XmmAppConst.spLoginInfoKey) != null;
  }

  var remoteRepository = XmmRemoteRepository();

  void reset() {
    _token = null;
    _user = XmmUser().obs;
    _login = null;
    _strategy = null;
    _myArticleInfoList.value.clear();
    _wallUserList = [];
    _articleInfoList = [];
    _videoInfoList = [];
  }

  Future<void> logout() async {
    XmmLogManger()
        .putLog(XmmLogType.clickEvent, {'page': XmmLogPages.pageLogout});
    await remoteRepository.logout();
    XmmSPUtil.remove(XmmAppConst.spLoginTokenKey);
    XmmImManager.instance.disconnect();
    reset();
  }

  Future<void> deleteAccount() async {
    XmmLogManger()
        .putLog(XmmLogType.clickEvent, {'page': XmmLogPages.pageDeleteAccount});
    await remoteRepository.deleteAccount();
    XmmSPUtil.remove(XmmAppConst.spLoginTokenKey);
    XmmSPUtil.remove(XmmAppConst.spLoginInfoKey);
    XmmSPUtil.remove(XmmAppConst.spVerKey);
    XmmSPUtil.remove(XmmAppConst.spWallUserListKey);
    XmmSPUtil.remove(XmmAppConst.spArticleInfoListKey);
    XmmSPUtil.remove(XmmAppConst.spMyArticleInfoListKey);
    XmmSPUtil.remove(XmmAppConst.spAutoTranslateKey);
    XmmSPUtil.remove(XmmAppConst.spVideoListKey);
    XmmImManager.instance.disconnect();
    reset();
  }

  ///快速登录
  Future<bool> fastLogin() async {
    XmmLogin login =
        await remoteRepository.oauth(4, XmmPlatformUtils.deviceId ?? "");
    _setLoginUser(login);
    return autoLogin();
  }

  ///苹果登录
  Future<bool> appleLogin(appleToken) async {
    XmmLogin login = await remoteRepository.oauth(3, appleToken);
    _setLoginUser(login);
    return autoLogin();
  }

  ///自动登录
  Future<bool> autoLogin() async {
    if (_login == null) {
      Object? loginJson = XmmSPUtil.get(XmmAppConst.spLoginInfoKey);
      if (loginJson is String) {
        _setLoginUser(XmmLogin.fromJson(jsonDecode(loginJson)));
      }
    }
    //验证登录token
    await remoteRepository.isValidToken(token ?? "");
    //获取策略信息
    _strategy = await remoteRepository.getStrategy();
    //获取配置信息
    String verKey = XmmSPUtil.get(XmmAppConst.spVerKey, defValue: "0");
    _appConfig = await remoteRepository.getConfigInfo(verKey);
    XmmSPUtil.set(XmmAppConst.spVerKey, _appConfig?.ver);
    //初始化本地数据和用户绑定。
    await _bindData();
    //连接im
    await connectIm();
    XmmLogManger()
        .putLog(XmmLogType.clickEvent, {'page': XmmLogPages.pageLoginSuccess});
    XmmXLogcat.d("login succeed bid=${_user.value.userId}");
    return true;
  }

  ///连接融云im
  Future<void> connectIm() async {
    //初始化融云
    String appKey = _appConfig?.getRCAppKey() ?? "";
    await XmmImManager.instance.init(appKey);
    //连接融云
    String token = _user.value.rongcloudToken ?? "";
    if (token.isEmpty) {
      //兜底获取token
      token = await remoteRepository.getRongCloudToken();
      _user.value.rongcloudToken = token;
    }
    await XmmImManager.instance.connect(token);
  }

  _setLoginUser(XmmLogin login) {
    XmmSPUtil.set(XmmAppConst.spLoginTokenKey, login.token);
    XmmSPUtil.set(XmmAppConst.spLoginInfoKey, login);
    _login = login;
    _user.value = login.userInfo;
    _token = login.token;
    //初始化自己发布的帖子数据
    var myArticleInfoListJson =
        XmmSPUtil.get(XmmAppConst.spMyArticleInfoListKey);
    if (myArticleInfoListJson != null) {
      var wallUser = XmmWallUser(
        author: user.userId,
        userId: user.userId,
        nickname: user.nickname,
        avatar: user.avatarUrl,
      );
      var myArticleInfoList = jsonDecode(myArticleInfoListJson);
      for (var element in myArticleInfoList) {
        var articleInfo = XmmArticleInfo.fromJson(element);
        articleInfo.wallUser = wallUser; //更新自己的用户信息
        _myArticleInfoList.value.add(articleInfo);
      }
    }
  }

  ///绑定作品列表和用户
  Future<void> _bindData() async {
    await _bindUserList();
    await _bindArticleList();
    await _bindVideoList();
    await _bindUserRelation();
  }

  Future<void> _bindUserList() async {
    try {
      var wallUserListJson = XmmSPUtil.get(XmmAppConst.spWallUserListKey);
      if (wallUserListJson != null) {
        //使用缓存数据
        var wallUserList = jsonDecode(wallUserListJson);
        for (var element in wallUserList) {
          _wallUserList.add(XmmWallUser.fromJson(element));
        }
        if (_wallUserList.isNotEmpty) {
          XmmXLogcat.d("_bindUserList parse data succeed in: cache");
          return;
        }
      }
      //获取用户列表
      var wallUserList = await remoteRepository.wallSearch();
      var articleInfoList = await XmmLocalRepository().getArticleList();
      var authorSet = articleInfoList.map((e) => e.author).toSet();
      for (int i = 0; i < authorSet.length; i++) {
        var wallUser = wallUserList.elementAt(i);
        wallUser.author = authorSet.elementAt(i);
        wallUser.giftNumber1 = Random().nextInt(50);
        wallUser.giftNumber2 = Random().nextInt(50);
        wallUser.giftNumber3 = Random().nextInt(50);
        _wallUserList.add(wallUser);
      }
      //缓存数据下次启动用
      XmmSPUtil.set(XmmAppConst.spWallUserListKey, jsonEncode(_wallUserList));
      XmmXLogcat.d("_bindUserList parse data succeed in: remote");
    } catch (e) {
      e.printError();
      XmmXLogcat.e(e);
    }
  }

  Future<void> _bindArticleList() async {
    try {
      var articleInfoListJson = XmmSPUtil.get(XmmAppConst.spArticleInfoListKey);
      if (articleInfoListJson != null) {
        //使用缓存数据
        var articleInfoList = jsonDecode(articleInfoListJson);
        for (var element in articleInfoList) {
          var articleInfo = XmmArticleInfo.fromJson(element);
          articleInfo.wallUser = _wallUserList
              .firstWhere((element) => element.author == articleInfo.author);
          _articleInfoList.add(articleInfo);
        }
        if (_articleInfoList.isNotEmpty) {
          XmmXLogcat.d("_bindArticleList parse data succeed in: cache");
          return;
        }
      }
      //获取本地作品数据
      var articleInfoList = await XmmLocalRepository().getArticleList();
      for (int i = 0; i < articleInfoList.length; i++) {
        var articleInfo = articleInfoList.elementAt(i);
        articleInfo.wallUser = _wallUserList
            .firstWhere((element) => element.author == articleInfo.author);
        _articleInfoList.add(articleInfo);
      }
      //缓存数据下次启动用
      XmmSPUtil.set(
          XmmAppConst.spArticleInfoListKey, jsonEncode(_articleInfoList));
      XmmXLogcat.d("_bindArticleList parse data succeed in: local");
    } catch (e) {
      XmmXLogcat.e(e);
    }
  }

  Future<void> _bindVideoList() async {
    try {
      var videoInfoListJson = XmmSPUtil.get(XmmAppConst.spVideoListKey);
      if (videoInfoListJson != null) {
        //使用缓存数据
        var videoInfoList = jsonDecode(videoInfoListJson);
        for (var element in videoInfoList) {
          var videoInfo = XmmVideoInfo.fromJson(element);
          _videoInfoList.add(videoInfo);
        }
        if (_videoInfoList.isNotEmpty) {
          XmmXLogcat.d("_bindVideoList parse data succeed in: cache");
          return;
        }
      }
      //获取视频列表
      var titleList = [
        "🌴 Outdoor fun.",
        "🌟 Shining star.",
        "📊 Scoreboard check.",
        "🎈 Play time!",
        "🏓 Double trouble.",
        "👟 Game shoes.",
        "🌈 Colorful play.",
        "🧢 Hat trick.",
        "🚀 Launch serve.",
        "👏 Great match!",
        "🎆 Celebration time.",
      ];
      var videoList = await remoteRepository.getVideoList();
      for (int i = 0; i < videoList.length; i++) {
        var videoInfo = videoList.elementAt(i);
        videoInfo.userId = _wallUserList.elementAt(i).userId;
        videoInfo.title = titleList.elementAt(i);
        _videoInfoList.add(videoInfo);
      }
      //缓存数据下次启动用
      XmmSPUtil.set(XmmAppConst.spVideoListKey, jsonEncode(_videoInfoList));
      XmmXLogcat.d("_bindVideoList parse data succeed in: remote");
    } catch (e) {
      XmmXLogcat.e(e);
    }
  }

  ///绑定本地用户列表跟登录用户的关系
  Future<void> _bindUserRelation() async {
    var followList = await remoteRepository.getFollowList();
    var blackList = await remoteRepository.getBlackList();
    updateUserRelation(blockList: blackList, followList: followList);
  }

  updateUserInfo() {
    _user.refresh();
    XmmSPUtil.set(XmmAppConst.spLoginInfoKey, login);
  }

  updateUserRelation({
    List<XmmBlockUser>? blockList,
    List<XmmUser>? followList,
  }) {
    for (var element in _wallUserList) {
      if (blockList != null) {
        element.isBlack =
            blockList.any((it) => it.broadcasterId == element.userId);
      }
      if (followList != null) {
        element.isFollow = followList.any((it) => it.userId == element.userId);
      }
    }
  }

  void addArticleByMy(XmmArticleInfo articleInfo) {
    _myArticleInfoList.add(articleInfo);
    XmmSPUtil.set(
      XmmAppConst.spMyArticleInfoListKey,
      jsonEncode(_myArticleInfoList),
    );
  }

  void removeArticleByMy(XmmArticleInfo articleInfo) {
    _myArticleInfoList.remove(articleInfo);
    XmmSPUtil.set(
      XmmAppConst.spMyArticleInfoListKey,
      jsonEncode(_myArticleInfoList),
    );
  }

  Future<bool> block(String userId) async {
    XmmLogManger().putLog(XmmLogType.clickEvent, {'page': XmmLogPages.pageBlock});
    var resp = await remoteRepository.black(userId);
    if (resp.success) {
      _wallUserList.firstWhere((element) => element.userId == userId).isBlack = true;
      await unfollow(userId); //拉黑需要把关注也取消
      XmmEventBus.instance.emit(XmmAppConst.eventBlockStatusUpdateKey, true);
    }
    return resp.success;
  }

  Future<bool> unblock(String userId) async {
    var resp = await remoteRepository.removeBlack(userId);
    if (resp.success) {
      _wallUserList.firstWhere((element) => element.userId == userId).isBlack = false;
      XmmEventBus.instance.emit(XmmAppConst.eventBlockStatusUpdateKey, false);
    }
    return resp.success;
  }

  Future<bool> follow(String userId) async {
    var resp = await remoteRepository.follow(userId);
    if (resp.success) {
      _wallUserList.firstWhere((element) => element.userId == userId).isFollow = true;
      XmmEventBus.instance.emit(XmmAppConst.eventFollowStatusUpdateKey, true);
    }
    return resp.success;
  }

  Future<bool> unfollow(String userId) async {
    var resp = await remoteRepository.unfollow(userId);
    if (resp.success) {
      _wallUserList.firstWhere((element) => element.userId == userId).isFollow = false;
      XmmEventBus.instance.emit(XmmAppConst.eventFollowStatusUpdateKey, false);
    }
    return resp.success;
  }

  void addWallUser(XmmWallUser user) {
    _wallUserList.add(user);
    updateWallUser();
  }

  ///更新了帖子信息后需要更新本地缓存
  void updateArticle() {
    XmmSPUtil.set(
      XmmAppConst.spArticleInfoListKey,
      jsonEncode(_articleInfoList),
    );
  }

  ///更新了用户信息后需要更新本地缓存
  void updateWallUser() {
    XmmSPUtil.set(
      XmmAppConst.spWallUserListKey,
      jsonEncode(_wallUserList),
    );
  }

  ///查找帖子
  Iterable<XmmArticleInfo> findArticle(String author) {
    return _articleInfoList.where((element) => element.author == author);
  }

  ///查找视频
  Iterable<XmmVideoInfo> findVideo(String userId) {
    return _videoInfoList.where((element) => element.userId == userId);
  }

  ///查找用户
  XmmWallUser findWallUser(String userId) {
    return _wallUserList.firstWhere(
      (element) => element.userId == userId,
      orElse: () => XmmWallUser(),
    );
  }
}
